package com.suray.wcs.service.init;

import com.google.common.collect.Lists;
import com.suray.basic.wcs.path.core.Node;
import com.suray.basic.wcs.path.enums.DirectionStatus;
import com.suray.basic.wcs.path.enums.NodeType;
import com.suray.basic.wcs.plc.core.Plc;
import com.suray.basic.wcs.plc.entity.PlcDeviceDB;
import com.suray.basic.wcs.plc.enums.Network;
import com.suray.basic.wcs.plc.enums.SinglePlcDeviceType;
import com.suray.basic.wcs.plc.pojo.HandleLifterBase;
import com.suray.basic.wcs.plc.pojo.oper.HandleAutoTraversingOper;
import com.suray.basic.wcs.plc.pojo.oper.HandleFoldingMachineOper;
import com.suray.basic.wcs.plc.pojo.oper.HandleMonomerConveyorOper;
import com.suray.basic.wcs.plc.pojo.oper.HandleToothHoistOper;
import com.suray.basic.wcs.plc.pojo.oper.lifter.LifterOper;
import com.suray.basic.wcs.plc.pojo.oper.lifter.TwoDirectionRgvLifterOper;
import com.suray.basic.wcs.plc.pojo.oper.lifter.ForkLifterOper;
import com.suray.basic.wcs.plc.pojo.oper.single.AutoTraversingOper;
import com.suray.basic.wcs.plc.pojo.oper.single.FoldingOper;
import com.suray.basic.wcs.plc.pojo.oper.single.MonomerConveyorOper;
import com.suray.basic.wcs.plc.pojo.oper.single.ToothHoistOper;
import com.suray.basic.wcs.plc.pojo.oper.single.lifter.LifterBaseOper;
import com.suray.basic.wcs.plc.service.impl.PlcDeviceDBServiceImpl;
import com.suray.basic.wcs.time.bo.WCSTimeModuleBO;
import com.suray.basic.wcs.utils.Coord;
import com.suray.basic.wcs.utils.LoggerUtil;
import com.suray.basic.wcs.utils.ModuleType;
import com.suray.basic.wcs.utils.WcsFuncUtil;
import com.suray.commin.core.utils.DateUtils;
import com.suray.commin.core.utils.SpringContextHolder;
import com.suray.rgv.*;
import com.suray.rgv.data.Rgv60InfoData;
import com.suray.rgv.data.RgvForkInfoData;
import com.suray.rgv.data.RgvSMInfoData;
import com.suray.system.run.SurayApplication;
import com.suray.system.run.random.code.thread.RunForGCodeThread;
import com.suray.wcs.res.enums.RgvGroupStatus;
import com.suray.wcs.res.enums.RgvStatus;
import com.suray.wcs.res.enums.RgvType;
import com.suray.wcs.res.msgparse.HeartSendBean;
import com.suray.wcs.service.core.path.api.impl.RgvSonNewTaskHandle;
import com.suray.wcs.service.core.util.LockNodeManager;
import com.suray.wcs.service.core.util.SysConfigUtil;
import com.suray.wcs.service.enums.*;
import com.suray.wcs.service.init.map.RgvMapManage;
import com.suray.wcs.service.plc.BarCodeScanner;
import com.suray.wcs.service.plc.util.LifterEventInterface;
import com.suray.wcs.service.plc.util.impl.ForkLifterEvent;
import com.suray.wcs.service.plc.util.impl.OriginalLifterEvent;
import com.suray.wcs.service.plc.util.impl.TwoDirectionRgvLifterEvent;
import com.suray.wcs.service.pojo.*;
import com.suray.wcs.service.rescontact.ToRes;
import com.suray.wcs.service.scheduling.RgvTaskTimer;
import com.suray.wcs.service.system.entity.*;
import com.suray.wcs.service.system.service.impl.*;
import com.suray.wcs.service.thread.*;
import com.suray.wcs.service.util.WcsUtil;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.DependsOn;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

@Component
@DependsOn(value = {"springContextHolder", "pathProperties", "sysConfigUtil"})
public class SystemInit {
    public static final List<Rgv> RGVS = new ArrayList<>();
    // 所有的库口
    public static final Map<Integer, PortDB> PORTS = new ConcurrentHashMap<>();
    public static final Map<String, String> URLS = new ConcurrentHashMap<>();
    public static final Map<String, List<ProgrammeDB>> PROGRAMMES = new ConcurrentHashMap<>();
    //仓库对象
    public static WareHouseDB wareHouseDB = new WareHouseDB();

    public static Date expirationDate = DateUtils.getNowDate();
    public static String expirationMsg = "";

    @Autowired
    private NodeDBServiceImpl nodedbServiceImpl;
    @Autowired
    private PortDBServiceImpl portService;
    @Autowired
    private WareHouseDBServiceImpl wareHouseDBService;

    private static CodeDBServiceImpl codeDBService = SpringContextHolder.getBean(CodeDBServiceImpl.class);
    private static PlcDeviceDBServiceImpl plcDeviceDBService = SpringContextHolder.getBean(PlcDeviceDBServiceImpl.class);
    public static final RgvMapDBServiceImpl rgvMapDBService = SpringContextHolder.getBean(RgvMapDBServiceImpl.class);
    private static NetAddressManageDBServiceImpl netAddressManageDBService =
            SpringContextHolder.getBean(NetAddressManageDBServiceImpl.class);

    public static RgvMapManage rgvMapManage = new RgvMapManage();

    private static Logger log = LoggerFactory.getLogger(SystemInit.class);
    private static NodeDBServiceImpl staticNodeDBServiceImpl;

    @PostConstruct
    public void init() {
        // 对所有设备初始化
        try {
            //模块APP线程
            new SurayApplication().SurayAppInit();
            staticNodeDBServiceImpl = nodedbServiceImpl;
            List<NodeDB> nodeDBS = staticNodeDBServiceImpl.getNodeDBList();
            WCSTimeModuleBO.OFFsetx = new HashMap<>();
            WCSTimeModuleBO.OFFsety = new HashMap<>();
            for (NodeDB nodeDB : nodeDBS) {
                WCSTimeModuleBO.OFFsetx.put(new Node(nodeDB.getGridx(), nodeDB.getGridy(), nodeDB.getGridz()), nodeDB.getOffsetx());
                WCSTimeModuleBO.OFFsety.put(new Node(nodeDB.getGridx(), nodeDB.getGridy(), nodeDB.getGridz()), nodeDB.getOffsety());
            }

            initSonRgv();

            rgvMapManage.loadRgvMaps(rgvMapDBService.list());

            wareHouseDB = wareHouseDBService.getCurWareHouseDB();

            //小车电量监控
            BatteryListenerThread.getBatteryListenerThread().start();
            // 小车初始化
            initRgvFromDB();

            // 系统启动之后延时然根据条码给小车定位之后再启动任务线程
            Thread.sleep(5000);
            RGVS.forEach(rgv -> {
                if (rgv.getGroundCode() != null && !rgv.checkRgvType(RgvType.RGV_SEER_COMM)) {
                    NodeDB nodedb = nodedbServiceImpl.findByBarcode(rgv.getGroundCode());
                    if (nodedb != null && nodedb.getGridType() != NodeType.L) {
                        try {
                            new Thread(() -> ToRes.getInstance(rgv).changeLocation(null, new Coord(nodedb.getGridx(), nodedb.getGridy(), nodedb.getGridz()))).start();
                        } catch (Exception e) {
                            log.info(rgv.getRgvName() + "系统启动时小车定位失败！", e);
                        }
                    }
                }
            });

            // 自动开启扫码称重外形检测线程
            List<PortDB> portDBList = portService.list();
            for (PortDB portDB : portDBList) {
                PORTS.put(portDB.getPortId(), portDB);
            }
            if (CollectionUtils.isNotEmpty(portDBList)) {
                for (PortDB portDB : PORTS.values()) {
                    if (StringUtils.isNotBlank(portDB.getWeightName()) || StringUtils.isNotBlank(portDB.getShapeName()) || StringUtils.isNotBlank(portDB.getScanName())) {
                        new BarCodeScanner().start(portDB);
                        new ScanTaskThread(portDB).start();
                    }
                }
            }

            // wms路径初始化
            initUrlMap();
//            Scada();
            //任务检测线程
            new TaskDBRemindThread().start();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 初始化子车
     */
    private void initSonRgv() {
        netAddressManageDBService.findNetAddressByType(NetAddressType.RGV_SON).forEach(netAddressManageDB -> {
            RgvInterface.newRgv(netAddressManageDB.getId(), netAddressManageDB.analyzeSeriesNumber(),
                    netAddressManageDB.getIp(), Integer.valueOf(netAddressManageDB.getPort()), ModuleType.RGV_SON);
        });
    }

    private void scada() {
        new Thread(() -> {
            for (Rgv rgv : RGVS) {
                ScadaDBSerciceImpl scadaDBService = SpringContextHolder.getBean(ScadaDBSerciceImpl.class);
                ScadaDB scadaDB = scadaDBService.getScadaDBByRgvNo(rgv.getRgvDB().getRgvNo());
                if (scadaDB != null) {
                    rgv.setOdo(scadaDB.getTravelDistance());
                    rgv.setAct(scadaDB.getOilDriveExecCount());
                }
            }
        }).start();
    }

    /**
     * 根据设备号获取RGV对像
     *
     * @param rgvNo
     * @return
     */
    public static Rgv getByRgvNo(Integer rgvNo) {
        Rgv returnRgv = null;
        if (rgvNo == null) {
            throw new IllegalArgumentException("设备号不能为空");
        }
        for (Rgv rgv : RGVS) {
            if (rgv.getRgvDB().getRgvNo().equals(rgvNo)) {
                returnRgv = rgv;
                break;
            }
        }
        if (returnRgv == null) {
            throw new IllegalStateException("找不到设备号: " + rgvNo + "对应的小车对象");
        }
        return returnRgv;
    }

    /**
     * 根据设备号获取RGV对像
     *
     * @param rgvNo
     * @return
     */
    public static Rgv getByRgvNoTask(Integer rgvNo) {
        Rgv returnRgv = null;
        if (rgvNo == null) {
            throw new IllegalArgumentException("设备号不能为空");
        }
        for (Rgv rgv : RGVS) {
            if (rgv.getRgvDB().getRgvNo().equals(rgvNo)) {
                returnRgv = rgv;
                break;
            }
        }
        if (returnRgv == null) {
            return null;
        }
        return returnRgv;
    }

    /**
     * 检测该车辆是否可去充电 条件 1.设置为自动充电 6. 不是充电中 2.已经设置充电位置 7. 未禁用 3.车辆状态不是NULL
     * 4.车辆位置不是NULl 5.车辆无故障
     *
     * @return
     */
    public static boolean checkIsCanCharge(Rgv rgv) {
        if (rgv.getRgvDB().getIsAutoCharge() && rgv.getRgvStatus() != null
                && rgv.getCurLocation() != null && rgv.getRgvStatus() != RgvStatus.OFF_LINE
                && rgv.getRgvStatus() != RgvStatus.CHARGING && rgv.getRgvStatus() != RgvStatus.ERROR) {
            return true;
        }
        return false;
    }

    /**
     * 检测该车辆是否回缓存位 条件 1.设置开启回缓存位 6. 不是充电中 2.已经设置充电位置 7. 未禁用 3.车辆状态不是NULL
     * 4.车辆位置不是NULl 5.车辆无故障
     *
     * @return
     */
    public static boolean checkIsGoFreeLocation(Rgv rgv) {
        WareHouseDBServiceImpl wareHouseDBService = SpringContextHolder.getBean(WareHouseDBServiceImpl.class);
        boolean flag = false;
        if (wareHouseDBService.getCurWareHouseDB().getFreeLocationFlag() && rgv.getRgvStatus() != null
                && rgv.getCurLocation() != null && rgv.getRgvStatus() != RgvStatus.OFF_LINE
                && rgv.getRgvStatus() != RgvStatus.CHARGING && rgv.getRgvStatus() != RgvStatus.ERROR) {
            flag = true;
        }
        return flag;
    }

    /**
     * 获取所有的RGV信息
     *
     * @return
     */
    public static List<RgvInfo> getRgvInfoList() {
        RgvDBServiceImpl rgvService = SpringContextHolder.getBean(RgvDBServiceImpl.class);
        List<RgvInfo> rgvList = new ArrayList<>();
        List<RgvDB> rgvDBList = rgvService.list();
        Collections.sort(rgvDBList, Comparator.comparing(RgvDB::getRgvNo));
        if (CollectionUtils.isNotEmpty(rgvDBList)) {
            for (Rgv rgv : RGVS) {
                for (RgvDB rgvDB : rgvDBList) {
                    if (rgv.getRgvDB().getRgvNo().equals(rgvDB.getRgvNo())) {
                        rgvDB.setLocation(rgv.getRgvDB().getLocation());
                        rgv.setRgvDB(rgvDB);
                        break;
                    }
                }
                RgvInfo rgvInfo = new RgvInfo();
                rgvInfo.setRgvNo(rgv.getRgvDB().getRgvNo());
                rgvInfo.setLocation(rgv.getCurLocationStr());
                rgvInfo.setRecordLocation(rgv.getRgvDB().getLocation());
                rgvInfo.setCurTaskId(rgv.getCurTask() != null ? rgv.getCurTask().getTaskId() : null);
                rgvInfo.setRgvStatus(rgv.getRgvStatus() != null ? rgv.getRgvStatus().getDescription() : RgvStatus.UNKNOWN.getDescription());
                rgvInfo.setBattery(rgv.getBattery());
                rgvInfo.setPing(rgv.getPing());
                rgvInfo.setRgvGroupStatus((rgv.getRgvDB().getOnline() ? RgvGroupStatus.parseByRgvStatus(rgv.getRgvStatus() != null ? rgv.getRgvStatus() : RgvStatus.OFF_LINE) : RgvGroupStatus.PAUSE_LINE).getRgvGroupStatus());
                rgvList.add(rgvInfo);
            }
        }
        return CollectionUtils.isNotEmpty(rgvList) ? rgvList : null;
    }

    /**
     * 获取所有的RGV信息
     *
     * @return
     */
    public static RgvInfoSingle getRgvInfoSingle(Rgv rgv) {
        RgvInfoSingle rgvInfoSingle = new RgvInfoSingle();
        rgvInfoSingle.setBarrierAtFour(rgv.getBarrierAtFour());
        rgvInfoSingle.setBarrierAtOne(rgv.getBarrierAtOne());
        rgvInfoSingle.setBarrierAtThree(rgv.getBarrierAtThree());
        rgvInfoSingle.setBarrierAtTwo(rgv.getBarrierAtTwo());
        rgvInfoSingle.setBattery(rgv.getBattery());
        rgvInfoSingle.setRgvType(rgv.getRgvDB().getRgvType());
        rgvInfoSingle.setChargeLocation(rgv.getRgvDB().getChargeLocation());
        rgvInfoSingle.setCurLocationStr(rgv.getCurLocationStr());
        rgvInfoSingle.setCurTaskId(rgv.getCurTask() != null ? rgv.getCurTask().getTaskId() : null);
        rgvInfoSingle.setDirection(rgv.getDirection());
        rgvInfoSingle.setErrorMessage(rgv.getErrorMessage());
        rgvInfoSingle.setStatusDescription(rgv.getStatusDescription());
        rgvInfoSingle.setGroundCode(rgv.getGroundCode());
        rgvInfoSingle.setHasPallet(rgv.getHasPallet().getValue());
        rgvInfoSingle.setIsAutoCharge(rgv.getRgvDB().getIsAutoCharge());
        rgvInfoSingle.setLocation(rgv.getRgvDB().getLocation());
        rgvInfoSingle.setLocationNode(rgv.getRgvDB().getLocationNode());
        rgvInfoSingle.setPalletStatus(rgv.getPalletStatus());
        rgvInfoSingle.setRgvNo(rgv.getRgvDB().getRgvNo());
        rgvInfoSingle.setRgvStatus(rgv.getRgvStatus());
        rgvInfoSingle.setCargoTaskId(rgv.getCargoTaskId());
        rgvInfoSingle.setPalletLoop(rgv.isPalletLoop());
        rgvInfoSingle.setReversLoop(rgv.isReversLoop());
        rgvInfoSingle.setUnLoadedLoop(rgv.isUnLoadedLoop());
        rgvInfoSingle.setLoadedLoop(rgv.isLoadedLoop());
        rgvInfoSingle.setTransferLoop(rgv.isTransferLoop());
        rgvInfoSingle.setDirectionStatus(DirectionStatus.XD_13.equals(rgv.getDirectionStatus()) || DirectionStatus.XD_1.equals(rgv.getDirectionStatus()) ? "巷道" :
                (DirectionStatus.PD_24.equals(rgv.getDirectionStatus()) || DirectionStatus.PD_2.equals(rgv.getDirectionStatus()) ? "坡道" : "未知"));
        TaskDB curTask = rgv.getCurTask();
        if (rgv.getCurTask() != null) {
            rgvInfoSingle.setTaskType(curTask.getTaskType().getDescription());
            if (TaskRgvProgress.RGV_TO_END.equals(curTask.getRgvProgress())) {
                rgvInfoSingle.setPurpose(curTask.getEndNodeStr());
            } else if (TaskRgvProgress.RGV_TO_START.equals(curTask.getRgvProgress())) {
                rgvInfoSingle.setPurpose(curTask.getStartNodeStr());
            }
        }
        rgvInfoSingle.setRgvChargeInfo(rgv.getRgvChargeInfo());
        rgvInfoSingle.setResVersion(rgv.getResParam().getResVersion());
        return rgvInfoSingle;
    }

    public static RgvSMInfoSingle RgvSMInfoSingle(RgvSM rgv) {
        RgvSMInfoData rgvSMInfoData = (rgv.getRgvCore()).getRgvSMInfoData();
        RgvSMInfoSingle rgvSMInfoSingle = new RgvSMInfoSingle();
        analyzeRgv60Data(rgvSMInfoData, rgvSMInfoSingle, rgv);
        rgvSMInfoSingle.setSonCmd(rgvSMInfoData.getSonCmd());
        rgvSMInfoSingle.setSonResult(rgvSMInfoData.getSonResult());
        rgvSMInfoSingle.setSonState(rgvSMInfoData.getSonState());
        rgvSMInfoSingle.setSonSpeed(rgvSMInfoData.getSonSpeed());
        rgvSMInfoSingle.setSonBcr(rgvSMInfoData.getSonBcr());
        rgvSMInfoSingle.setSonEle(rgvSMInfoData.getSonEle());
        rgvSMInfoSingle.setSonLife(rgvSMInfoData.getSonLife());
        rgvSMInfoSingle.setSonMoveSpeed(rgvSMInfoData.getSonMoveSpeed());
        rgvSMInfoSingle.setSonMoveAcc(rgvSMInfoData.getSonMoveAcc());
        rgvSMInfoSingle.setSonMoveDec(rgvSMInfoData.getSonMoveDec());
        rgvSMInfoSingle.setSonRgvLocation(rgv.getSonRgvLocation() == null ? "" : rgv.getSonRgvLocation().toString());
        rgvSMInfoSingle.setCurActionNo(rgvSMInfoData.getCurActionNo());
        rgvSMInfoSingle.setMotherRgvGroundCode(rgvSMInfoData.getMotherRgvGroundCode());
        rgvSMInfoSingle.setIsSonRgvEnable(rgvSMInfoData.getIsSonRgvEnable());
        rgvSMInfoSingle.setLeftRgvSignal(rgvSMInfoData.getLeftRgvSignal());
        rgvSMInfoSingle.setRightRgvSignal(rgvSMInfoData.getRightRgvSignal());
        rgvSMInfoSingle.setRgvSonTaskStatus(rgvSMInfoData.getRgvSonTaskStatus());
        rgvSMInfoSingle.setRgvSonTaskId(rgvSMInfoData.getRgvSonTaskId());
        rgvSMInfoSingle.setRgvSonFinishSegment(rgvSMInfoData.getRgvSonFinishSegment());
        rgvSMInfoSingle.setRgvSonTaskResult(rgvSMInfoData.getRgvSonTaskResult());
        rgvSMInfoSingle.setPalletLoop(rgv.isPalletLoop());
        rgvSMInfoSingle.setReversLoop(rgv.isReversLoop());
        rgvSMInfoSingle.setUnLoadedLoop(rgv.isUnLoadedLoop());
        rgvSMInfoSingle.setLoadedLoop(rgv.isLoadedLoop());
        rgvSMInfoSingle.setTransferLoop(rgv.isTransferLoop());

        if (rgvSMInfoData.getIsSonRgvEnable()) {
            if (rgvSMInfoData.getSonAlarm() > 0) {
                rgvSMInfoSingle.setSonAlarm(rgvSMInfoData.getSonAlarm().toString());
            }
            if (rgvSMInfoData.getSonError() > 0) {
                rgvSMInfoSingle.setSonError(codeDBService.getCodeDescByType(CodeType.RGV_SON_TYPE.getState(),
                        rgvSMInfoData.getSonError()));
            }
            if (rgvSMInfoData.getRgvSonTaskErrorCode() > 0) {
                rgvSMInfoSingle.setRgvSonTaskErrorCode(codeDBService.getCodeDescByType(CodeType.RGV_SON_TYPE.getState(),
                        rgvSMInfoData.getRgvSonTaskErrorCode()));
            }
            rgvSMInfoSingle.setHasSonRgv(rgvSMInfoData.getHasSonRgv() ? "在母车内" : "不在母车内");
        }
        return rgvSMInfoSingle;
    }

    public static RgvForkInfoSingle RgvForkInfoSingle(RgvFork rgv) {
        RgvForkInfoData rgvForkInfoData = (rgv.getRgvCore()).getRgvForkInfoData();
        RgvForkInfoSingle rgvForkInfoSingle = new RgvForkInfoSingle();
        analyzeRgv60Data(rgvForkInfoData, rgvForkInfoSingle, rgv);
        rgvForkInfoSingle.setForkHeight(rgvForkInfoData.getForkHeight() == null ? null :
                rgvForkInfoData.getForkHeight().toString() + " mm");
        rgvForkInfoSingle.setIsForkArrived(rgvForkInfoData.getIsForkArrived());
        rgvForkInfoSingle.setForkMode(rgvForkInfoData.getForkMode());
        rgvForkInfoSingle.setForkLiftDis(rgvForkInfoData.getForkLiftDis() == null ? null :
                rgvForkInfoData.getForkLiftDis().toString() + " mm");
        rgvForkInfoSingle.setForkLiftDownHeight(rgvForkInfoData.getForkLiftDownHeight() == null ? null :
                rgvForkInfoData.getForkLiftDownHeight().toString() + " mm");
        rgvForkInfoSingle.setForkHeightErrorRange(rgvForkInfoData.getForkHeightErrorRange() == null ? null :
                rgvForkInfoData.getForkHeightErrorRange().toString() + " mm");
        return rgvForkInfoSingle;
    }

    public static Rgv60InfoSingle Rgv60InfoSingle(Rgv60 rgv) {
        Rgv60InfoData rgv60InfoData = (rgv.getRgvCore()).getRgv60InfoData();
        Rgv60InfoSingle rgv60InfoSingle = new Rgv60InfoSingle();
        analyzeRgv60Data(rgv60InfoData, rgv60InfoSingle, rgv);
        return rgv60InfoSingle;
    }

    private static void analyzeRgv60Data(Rgv60InfoData rgv60InfoData, Rgv60InfoSingle rgv60InfoSingle, Rgv rgv) {
        rgv60InfoSingle.setRgvNo(rgv.getRgvDB().getRgvNo());
        rgv60InfoSingle.setTaskId(rgv.getCurTask() != null ? rgv.getCurTask().getTaskId() : null);
        rgv60InfoSingle.setCargoTaskId(rgv.getCargoTaskId());
        rgv60InfoSingle.setWcsTaskType(rgv.getCurTask() != null ? rgv.getCurTask().getTaskType().toString() : null);
        rgv60InfoSingle.setCurrentStation(rgv60InfoData.getCurrentStation());
        rgv60InfoSingle.setIsAutoCharge(rgv.getRgvDB().getIsAutoCharge());
        rgv60InfoSingle.setLastLocation(rgv.getRgvDB().getLocation());
        rgv60InfoSingle.setChargeLocation(rgv.getRgvDB().getChargeLocation());
        rgv60InfoSingle.setRelocStatus(rgv60InfoData.getRelocStatus().toString());
        rgv60InfoSingle.setRobotCurrentStation(rgv60InfoData.getRobotCurrentStation());
        rgv60InfoSingle.setLastStation(rgv60InfoData.getLastStation());
        rgv60InfoSingle.setSerialNum(rgv60InfoData.getSerialNum());
        rgv60InfoSingle.setOnLine(rgv60InfoData.isOnLine() ? "在线" : "离线");
        rgv60InfoSingle.setConfigOnLine(rgv60InfoData.isConfigOnLine() ? "在线" : "离线");
        rgv60InfoSingle.setControlOnLine(rgv60InfoData.isControlOnLine() ? "在线" : "离线");
        rgv60InfoSingle.setRouteOnLine(rgv60InfoData.isRouteOnLine() ? "在线" : "离线");
        rgv60InfoSingle.setRobotStateOnLine(rgv60InfoData.isRobotStateOnLine() ? "在线" : "离线");
        rgv60InfoSingle.setHasRgvAuthor(rgv60InfoData.isHasRgvAuthor());
        rgv60InfoSingle.setRgvStatus(rgv60InfoData.getRgvStatus().toString());
        rgv60InfoSingle.setRgvActStatus(rgv60InfoData.getRgvActStatus().toString());

        List<String> errors = new ArrayList<>();
        rgv60InfoData.getErrorInfos().forEach(errorInfo -> {
            errors.add(errorInfo.getErrorCode() + ":" + errorInfo.getErrorMessage());
        });
        rgv60InfoSingle.setErrorInfos(errors);

        if (rgv.getRgvStatus() == RgvStatus.ERROR) {
            if (StringUtils.isNotEmpty(rgv.getErrorMessage())) {
                rgv60InfoSingle.setHighestError(rgv.getErrorMessage());
            }
        }

        rgv60InfoSingle.setPalletStatus(rgv.getPalletStatus());
        rgv60InfoSingle.setPalletEnable(rgv60InfoData.getPalletEnable() ? "启用" : "未启用");
        rgv60InfoSingle.setPalletActionErrorCode(rgv60InfoData.getPalletActionErrorCode());
        rgv60InfoSingle.setHasCargo(rgv60InfoData.getHasCargo() ? "有货" : "无货");
        rgv60InfoSingle.setX(rgv60InfoData.getX());
        rgv60InfoSingle.setY(rgv60InfoData.getY());
        rgv60InfoSingle.setAngle(rgv60InfoData.getAngle());
        rgv60InfoSingle.setConfidence(rgv60InfoData.getConfidence());
        rgv60InfoSingle.setBlocked(rgv60InfoData.getBlocked() ? "阻挡" : "未阻挡");
        rgv60InfoSingle.setBatSoc(rgv60InfoData.getBatSoc());
        rgv60InfoSingle.setBatTemp(rgv60InfoData.getBatTemp());
        rgv60InfoSingle.setBatVolt(rgv60InfoData.getBatVolt());
        rgv60InfoSingle.setBatCur(rgv60InfoData.getBatCur());
        rgv60InfoSingle.setAutoCharge(rgv60InfoData.getAutoCharge() ? "连接" : "未连接");
        rgv60InfoSingle.setCharging(rgv60InfoData.getCharging() ? "充电中" : "未充电");
        rgv60InfoSingle.setTaskStatus(rgv60InfoData.getTaskStatus().toString());
        rgv60InfoSingle.setTargetStation(rgv60InfoData.getTargetStation());
        rgv60InfoSingle.setTaskType(rgv60InfoData.getTaskType().toString());
        rgv60InfoSingle.setLoadMapStatus(rgv60InfoData.getLoadMapStatus().toString());
        rgv60InfoSingle.setMode(rgv60InfoData.getMode().toString());
        rgv60InfoSingle.setRollerMode(rgv60InfoData.getRollerMode()==null?"未知":rgv60InfoData.getRollerMode().toString());
        rgv60InfoSingle.setCurrentMap(rgv60InfoData.getCurrentMap());
        rgv60InfoSingle.setCurrentMapMD5(rgv60InfoData.getCurrentMapMD5());
        rgv60InfoSingle.setWifiStrength(rgv60InfoData.getWifiStrength());
        rgv60InfoSingle.setRobotName(rgv60InfoData.getRobotName());
        rgv60InfoSingle.setMaps(rgv60InfoData.getMaps());
        rgv60InfoSingle.setOdo(rgv60InfoData.getOdo());
        rgv60InfoSingle.setTodayOdo(rgv60InfoData.getTodayOdo());

        rgv60InfoSingle.setRunningTimeSeconds(rgv60InfoData.getRunningTime().seconds);
        rgv60InfoSingle.setRunningTimeMinute(rgv60InfoData.getRunningTime().minute);
        rgv60InfoSingle.setRunningTimeHour(rgv60InfoData.getRunningTime().hour);
        rgv60InfoSingle.setRunningTimeDay(rgv60InfoData.getRunningTime().day);

        rgv60InfoSingle.setCurRunningTimeSeconds(rgv60InfoData.getCurRunningTime().seconds);
        rgv60InfoSingle.setCurRunningTimeMinute(rgv60InfoData.getCurRunningTime().minute);
        rgv60InfoSingle.setCurRunningTimeHour(rgv60InfoData.getCurRunningTime().hour);
        rgv60InfoSingle.setCurRunningTimeDay(rgv60InfoData.getCurRunningTime().day);

        rgv60InfoSingle.setControlVolt(rgv60InfoData.getControlVolt());
        rgv60InfoSingle.setControlTemp(rgv60InfoData.getControlTemp());
        rgv60InfoSingle.setControlWet(rgv60InfoData.getControlWet());
        rgv60InfoSingle.setChargeNum(rgv60InfoData.getChargeNum());
        rgv60InfoSingle.setPermitMaxChgVolt(rgv60InfoData.getPermitMaxChgVolt());
        rgv60InfoSingle.setPermitMaxChgCur(rgv60InfoData.getPermitMaxChgCur());
        rgv60InfoSingle.setBlockX(rgv60InfoData.getBlockX());
        rgv60InfoSingle.setBlockY(rgv60InfoData.getBlockY());
        rgv60InfoSingle.setDriveEmc(rgv60InfoData.getDriveEmc() ? "急停" : "未急停");
        rgv60InfoSingle.setHoldBrake(rgv60InfoData.getHoldBrake() ? "抱闸" : "未抱闸");
        rgv60InfoSingle.setIsStop(rgv60InfoData.getIsStop() ? "静止" : "未静止");
        rgv60InfoSingle.setTargetX(rgv60InfoData.getTargetX());
        rgv60InfoSingle.setTargetY(rgv60InfoData.getTargetY());
        rgv60InfoSingle.setTargetR(rgv60InfoData.getTargetR());
        rgv60InfoSingle.setRobotNote(rgv60InfoData.getRobotNote());
        rgv60InfoSingle.setDI(rgv60InfoData.getDI());
        rgv60InfoSingle.setDO(rgv60InfoData.getDO());
        Boolean[] rDI=rgv60InfoData.getDI();
        List<String> di = new ArrayList<>();
        for(int i=0;i<9;i++){
         di.add(rDI[i]+"");
        }
        rgv60InfoSingle.setRobotDI(di);
        Boolean[] rDO=rgv60InfoData.getDO();
        List<String> rdo = new ArrayList<>();
        for(int i=0;i<9;i++){
            rdo.add(rDO[i]+"");
        }
        rgv60InfoSingle.setRobotDO(rdo);
    }

    /**
     * 获取所有的RGV信息
     *
     * @return
     */
    public static List<RgvInfoFloor> getRgvInfoFloorList(Integer floor) {
        RgvDBServiceImpl rgvService = SpringContextHolder.getBean(RgvDBServiceImpl.class);
        if (floor == null) {
            return null;
        }
        List<RgvInfoFloor> rgvList = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(RGVS)) {
            for (Rgv rgv : RGVS) {
                if (rgv.getRgvDB().getLocationNode().getZ() == floor) {
                    RgvInfoFloor rgvInfoFloor = new RgvInfoFloor();
                    rgvInfoFloor.setRgvNo(rgv.getRgvDB().getRgvNo());
                    rgvInfoFloor.setLocationNode(rgv.getRgvDB().getLocationNode());
                    rgvInfoFloor.setPalletStatus(rgv.getPalletStatus());
                    rgvInfoFloor.setRgvStatus(rgv.getRgvStatus());
                    rgvInfoFloor.setDirection(rgv.getDirection());
                    rgvInfoFloor.setWaitReleaseNode(rgvInfoFloor.coords(rgv.getWaitReleaseNode()));
                    rgvInfoFloor.setExecuteNodeList(rgvInfoFloor.coords(rgv.getExecuteNodeList()));
                    if (rgv.checkRgvType(RgvType.RGV_SON_MOTHER)) {
                        rgvInfoFloor.setSonState(((RgvSM) rgv).getRgvCore().getSonRgvStatus());
                        rgvInfoFloor.setSonLocationNode(rgv.getRgvDB().getSonLocationNode());
                    }
                    rgvInfoFloor.setRgvType(rgv.getRgvDB().getRgvType());
                    rgvList.add(rgvInfoFloor);
                    //查询所有车辆如果是就绪联机车辆就且备注有时间字段就清空
                    if (rgv.getRgvDB().getOnline() && rgv.getRgvStatus().equals(RgvStatus.READY) && rgv.getRgvDB().getRemark() != null) {
                        rgvService.updateRgvRemarkOFFLineTime(null, rgv.getRgvDB().getRgvNo());
                    }
                }
            }
        }
        rgvList.sort(Comparator.comparing(RgvInfoFloor::getRgvNo));
        return rgvList;
    }

    /**
     * 获取当前库区的所有车
     *
     * @return
     */
    public static List<Rgv> getRgvList() {
        List<Rgv> rgvList = new ArrayList<>();
        for (Rgv rgv : RGVS) {
            rgvList.add(rgv);
        }
        return rgvList;
    }

    /**
     * 获取当前库区非当前层的所有车
     *
     * @return List<Rgv> 当前库区当前层小车信息
     * @author rbj
     */
    public static List<Rgv> getOnlineAndLocationRgvList() {
        List<Rgv> rgvList = new ArrayList<>();
        for (Rgv rgv : RGVS) {
            try {
                if (rgv.getRgvDB().getOnline() && rgv.getCurLocation() != null) {
                    rgvList.add(rgv);
                }
            } catch (Exception e) {
                log.error("获取当前库区的车{}出错", rgv.getRgvDB().getRgvNo());
            }
        }
        return rgvList;
    }

    /**
     * 获取非当前层本分区的小车
     *
     * @return List<Rgv> 当前库区当前层小车信息
     * @author rbj
     */
    public static List<Rgv> getNoCurrentFloorZoneRgvList(int floor, Integer zoneId) {
        List<Rgv> rgvList = new ArrayList<>();
        for (Rgv rgv : RGVS) {
            try {
                if (rgv.getRgvDB().getOnline()
                        && rgv.getCurLocation() != null
                        && floor != rgv.getCurLocation().getZ()
                        && isZoneRgv(rgv, zoneId)) {
                    rgvList.add(rgv);
                }
            } catch (Exception e) {
                log.error("获取当前库区非当前层已分配的车{}出错", rgv.getRgvDB().getRgvNo());
            }
        }
        return rgvList;
    }

    /**
     * 获取当前库区当前层当前分区的所有车
     *
     * @param floor 层
     * @return List<Rgv> 当前库区当前层小车信息
     * @author rbj
     */
    public static List<Rgv> getCurrentFloorZoneRgvList(int floor, Integer zoneId) {
        List<Rgv> rgvList = new ArrayList<>();
        for (Rgv rgv : RGVS) {
            try {
                if (rgv.getRgvDB().getOnline()
                        && rgv.getCurLocation() != null
                        && floor == rgv.getCurLocation().getZ()
                        && isZoneRgv(rgv, zoneId)) {
                    if (rgv.getRgvStatus() == RgvStatus.CHARGING && rgv.getBattery() < rgv.getRgvDB().getAssignBatterySize()) {
                        continue;
                    }
                    rgvList.add(rgv);
                }
            } catch (Exception e) {
                log.error("获取当前库区当前层的车{}出错", rgv.getRgvDB().getRgvNo());
            }
        }
        return rgvList;
    }

    /**
     * 获取当前库区当前层当前分区的所有车
     *
     * @param floor 层
     * @return List<Rgv> 当前库区当前层小车信息
     * @author rbj
     */
    public static List<Rgv> getCurrentFloorNoZoneAssignedRgvList(int floor, Set<Integer> rgvNos, Integer zoneId) {
        List<Rgv> rgvList = new ArrayList<>();
        for (Rgv rgv : RGVS) {
            try {
                if (rgv.getRgvDB().getOnline()
                        && rgvNos.contains(rgv.getRgvDB().getRgvNo())
                        && rgv.getCurLocation() != null
                        && floor == rgv.getCurLocation().getZ()
                        && !isZoneRgv(rgv, zoneId)) {
                    rgvList.add(rgv);
                }
            } catch (Exception e) {
                log.error("获取当前库区当前层的车{}出错", rgv.getRgvDB().getRgvNo());
            }
        }
        return rgvList;
    }

    /**
     * 获取当前库区当前层当前分区的所有车
     *
     * @param floor 层
     * @return List<Rgv> 当前库区当前层小车信息
     * @author rbj
     */
    public static List<Rgv> getCurrentFloorNoZoneNoAssignedRgvList(int floor, Set<Integer> rgvNos, Integer zoneId) {
        List<Rgv> rgvList = new ArrayList<>();
        for (Rgv rgv : RGVS) {
            try {
                if (rgv.getRgvDB().getOnline()
                        && !rgvNos.contains(rgv.getRgvDB().getRgvNo())
                        && rgv.getCurLocation() != null
                        && floor == rgv.getCurLocation().getZ()
                        && !isZoneRgv(rgv, zoneId)) {
                    rgvList.add(rgv);
                }
            } catch (Exception e) {
                log.error("获取当前库区当前层的车{}出错", rgv.getRgvDB().getRgvNo());
            }
        }
        return rgvList;
    }

    private static boolean isZoneRgv(Rgv rgv, Integer zoneId) {
        if (zoneId == null) {
            return true;
        }
        if (rgv.getCurLocation() != null) {
            NodeDB nodeDB = staticNodeDBServiceImpl.getNodeDB(rgv.getCurLocation());
            if (zoneId.equals(nodeDB.getZoneId())) {
                return true;
            }
        }
        return false;
    }

    /**
     * 获取当前库区已分配任务的小车
     *
     * @return List<Rgv> 当前库区当前层小车信息
     * @author rbj
     */
    public static List<Rgv> getCurrentFloorAssignedRgvList(Set<Integer> rgvNos) {
        List<Rgv> rgvList = new ArrayList<>();
        for (Rgv rgv : RGVS) {
            try {
                if (rgvNos.contains(rgv.getRgvDB().getRgvNo())
                        && rgv.getCurLocation() != null && rgv.getRgvDB().getOnline()) {
                    rgvList.add(rgv);
                }
            } catch (Exception e) {
                log.error("获取当前库区当前层的车{}出错", rgv.getRgvDB().getRgvNo());
            }
        }
        return rgvList;
    }

    /**
     * 获取非当前层已分配任务的小车
     *
     * @return List<Rgv> 当前库区当前层小车信息
     * @author rbj
     */
    public static List<Rgv> getNoCurrentFloorAssignedRgvList(int floor, Set<Integer> rgvNos, Integer zoneId) {
        List<Rgv> rgvList = new ArrayList<>();
        for (Rgv rgv : RGVS) {
            try {
                if (rgv.getRgvDB().getOnline()
                        && rgvNos.contains(rgv.getRgvDB().getRgvNo())
                        && rgv.getCurLocation() != null
                        && floor != rgv.getCurLocation().getZ()
                        && isZoneRgv(rgv, zoneId)) {
                    rgvList.add(rgv);
                }
            } catch (Exception e) {
                log.error("获取当前库区非当前层已分配的车{}出错", rgv.getRgvDB().getRgvNo());
            }
        }
        return rgvList;
    }

    /**
     * 获取当前库区非当前层的所有车
     *
     * @param floor 层
     * @return List<Rgv> 当前库区当前层小车信息
     * @author rbj
     */
    public static List<Rgv> getNotCurrentFloorRgvList(int floor, Set<Integer> rgvNos, Integer zoneId) {
        List<Rgv> rgvList = new ArrayList<>();
        for (Rgv rgv : RGVS) {
            try {
                if (rgv.getRgvDB().getOnline()
                        && !rgvNos.contains(rgv.getRgvDB().getRgvNo())
                        && rgv.getCurLocation() != null
                        && floor != rgv.getRgvDB().getLocationNode().getZ()
                        && isZoneRgv(rgv, zoneId)) {
                    rgvList.add(rgv);
                }
            } catch (Exception e) {
                log.error("获取当前库区非当前层的车{}出错", rgv.getRgvDB().getRgvNo());
            }
        }
        return rgvList;
    }

    /**
     * 根据库区获取rgvdbs
     */
    public static List<RgvDB> getManualOperRgvs() {
        List<RgvDB> rgvDBS = new ArrayList<>();
        for (Rgv rgv : SystemInit.RGVS) {
            rgvDBS.add(rgv.getRgvDB());
        }
        return rgvDBS;
    }

    /**
     * 获取指定库区所有可执行任务的RGV对象
     * 只要是未下线均为可运行
     *
     * @return
     */
    public static List<Rgv> getCanRunRgvList() {
        List<Rgv> canRunRgvList = new ArrayList<>();
        for (Rgv rgv : RGVS) {
            if (rgv.getCurLocation() != null && rgv.getRgvDB().getOnline()) {
                canRunRgvList.add(rgv);
            }
        }
        return canRunRgvList;
    }

    /**
     * 获取指定库区所有可执行任务的RGV对象
     *
     * @return
     */
    public static List<Rgv> getCanRunRgvListWithoutDisable() {
        List<Rgv> canRunRgvList = new ArrayList<>();
        for (Rgv rgv : RGVS) {
            if (rgv.getRgvStatus() != null && rgv.getCurLocation() != null && rgv.getRgvDB().getOnline()) {
                canRunRgvList.add(rgv);
            }
        }
        return canRunRgvList;
    }

    public static Rgv newRgv(RgvDB rgvDB, int mapVersion, Boolean sonRgvDirectionX, Boolean sonRgvDirectionY) {
        Rgv rgv = null;
        if (rgvDB.getRgvType().equals(RgvType.RGV_SIX_POINT_ZERO.getValue())) {
            try {
                //6代车
                rgv = new Rgv60(rgvDB, (Rgv60Interface) RgvInterface.newRgv(rgvDB.getRgvNo(),
                        rgvDB.getRgvNo() + "号小车", rgvDB.getRgvIp(), null, ModuleType.RGV_60),
                        ModuleType.RGV_60);
            } catch (Exception e) {
                WcsFuncUtil.exceptionLog(e, SystemInit.class);
            }
        } else if (rgvDB.getRgvType().equals(RgvType.RGV_ROLLER.getValue())) {
            try {
                //滚筒车
                rgv = new RgvRoller(rgvDB, (RgvRollerInterface) RgvInterface.newRgv(rgvDB.getRgvNo(),
                        rgvDB.getRgvNo() + "号小车", rgvDB.getRgvIp(), null, ModuleType.RGV_ROLLER),
                        ModuleType.RGV_ROLLER);
            } catch (Exception e) {
                WcsFuncUtil.exceptionLog(e, SystemInit.class);
            }
        } else if (rgvDB.getRgvType().equals(RgvType.RGV_SON_MOTHER.getValue())) {
            try {
                //子母车
                rgv = new RgvSM(rgvDB, (RgvSMInterface) RgvInterface.newRgv(rgvDB.getRgvNo(),
                        rgvDB.getRgvNo() + "号小车", rgvDB.getRgvIp(), null, ModuleType.RGV_SON_MOTHER),
                        ModuleType.RGV_SON_MOTHER);
                changeRgvSMSonRgv((RgvSM) rgv, rgvDB);
                NodeDBServiceImpl nodeDBService = SpringContextHolder.getBean(NodeDBServiceImpl.class);
                RgvSMInterface rgvSM = ((RgvSM) rgv).getRgvCore();
                rgvSM.setSonRgvDirectionX(sonRgvDirectionX);
                rgvSM.setSonRgvDirectionY(sonRgvDirectionY);
                new Thread(() -> {
                    try {
                        rgvSM.sonRgvChangeSpeedConfig(rgvDB.getSonRgvSpeed(), rgvDB.getSonRgvAccSpeed(),
                                rgvDB.getSonRgvDecSpeed());
                    } catch (Throwable e) {
                        WcsFuncUtil.exceptionLog(e, SystemInit.class);
                    }
                }).start();
                try {
                    if (!rgvDB.getLocationNode().equals(rgvDB.getSonLocationNode())) {
                        Node sonNode = nodeDBService.getNode(rgvDB.getSonLocationNode());
                        if (sonNode.getNodeType() == NodeType.R) {
                            throw new RuntimeException();
                        }
                        Set<Coord> coords = RgvSonNewTaskHandle.analyzeLineNodes(rgvDB.getLocationNode(),
                                rgvDB.getSonLocationNode());
                        RgvSonNewTaskHandle.lockNodes(LockNodeManager.getUnLockedNode(coords), (RgvSM) rgv);
                    }
                } catch (Exception e) {
                    LoggerUtil.error("锁定子母车路径失败", SystemInit.class);
                    WcsUtil.notification("锁定子母车路径失败, 有撞车风险, 请尽快把子车手动开会母车, 并刷新子车状态",
                            NotificationTypeEnum.ERROR);
                    if (rgvDB.getSonLocationNode() != null) {
                        LockNodeManager.lockNode(rgvDB.getSonLocationNode(), rgv);
                    }
                }
            } catch (Exception e) {
                WcsFuncUtil.exceptionLog(e, SystemInit.class);
            }
        } else if (rgvDB.getRgvType().equals(RgvType.RGV_FORK.getValue())) {
            try {
                //叉车
                rgv = new RgvFork(rgvDB, (RgvForkInterface) RgvInterface.newRgv(rgvDB.getRgvNo(),
                        rgvDB.getRgvNo() + "号小车", rgvDB.getRgvIp(), null, ModuleType.RGV_FORK),
                        ModuleType.RGV_FORK);
                ((RgvFork) rgv).resetForkParam();
            } catch (Exception e) {
                WcsFuncUtil.exceptionLog(e, SystemInit.class);
            }
        } else {
            rgv = new Rgv(rgvDB);
        }
        HeartSendBean heartSendBean = new HeartSendBean();
        heartSendBean.setMapVersion(mapVersion);
        rgv.setRgvHeart(heartSendBean);
        rgv.setRejectStatus(Rgv.RejectStatus.NONE);
        new RunForGCodeThread(rgv).start();
        //小车任务线程
        RgvExecuteThread rgvExecuteThread = new RgvExecuteThread("rgv_" + rgvDB.getRgvNo(), rgv);
        rgv.setRgvExecuteThread(rgvExecuteThread);
        rgvExecuteThread.start();
        new RgvInitThread(rgv).start();
        RGVS.add(rgv);
        LockNodeManager.updateLocationLock(rgv);
        // 启动小车心跳检测线程
        new WcsHeartThread(rgv).start();
        // 启动定时任务线程
        new RgvTaskTimer(rgv).start();
        // 启动自动定位线程
        new AutomaticPositioning(rgv).start();
        // 小车释放锁定资源线程
        new RgvReleaseLockThread(rgv).start();
        // 启动充电异常线程
        new ChargeErrorTimer(rgv).start();
        if (SysConfigUtil.PRE_ASSIGN_ADJUST) {
            // 调整预分配结果
            // 每辆车的状态，任务数量，调整分配的条件
            new AssignTaskThread(rgv).start();
        }
        //小车电量监控
        BatteryListenerThread.getBatteryListenerThread().addRgv(rgv);
        return rgv;
    }

    public static void changeRgvSMSonRgv(RgvSM rgv, RgvDB rgvDB) {
        NetAddressManageDB netAddressManageDB = netAddressManageDBService.getById(rgvDB.getMappedSonRgv());
        if (netAddressManageDB != null) {
            RgvSonInterface rgvSonInterface =
                    (RgvSonInterface) RgvInterface.getInstance(netAddressManageDB.analyzeSeriesNumber());
            rgv.getRgvCore().changeSonRgv(rgvSonInterface);
        }
    }

    public static void initRgvFromDB() {
        RgvDBServiceImpl rgvService = SpringContextHolder.getBean(RgvDBServiceImpl.class);
        WareHouseDB wareHouseDB = SpringContextHolder.getBean(WareHouseDBServiceImpl.class).getCurWareHouseDB();
        int mapVersion = wareHouseDB.getMapVersion();
        Boolean sonRgvDirectionX = wareHouseDB.getSonRgvDirectionX();
        Boolean sonRgvDirectionY = wareHouseDB.getSonRgvDirectionY();
        // 获取所有数据库中存在的小车
        List<RgvDB> rgvDBList = rgvService.list();
        Collections.sort(rgvDBList, Comparator.comparing(RgvDB::getRgvNo));
        if (rgvDBList.isEmpty()) {
            log.warn("数据库中无小车记录存在");
        }
        // 唯一实例化RGV对象的代码, 获取小车信息, 初始化线程
        rgvDBList.forEach(rgvDB -> {
            try {
                newRgv(rgvDB, mapVersion, sonRgvDirectionX, sonRgvDirectionY);
            } catch (Exception e) {
                WcsFuncUtil.exceptionLog(e, SystemInit.class);
                LoggerUtil.warn("小车创建失败：" + rgvDB, SystemInit.class);
            }
        });
    }

    public static void initUrlMap() {
        WmsUrlDBServiceImpl wmsUrlDBService = SpringContextHolder.getBean(WmsUrlDBServiceImpl.class);
        List<WmsUrlDB> list = wmsUrlDBService.list();
        if (list.isEmpty()) {
            log.warn("数据库中无接口路径数据存在");
        }
        for (WmsUrlDB wmsUrlDB : list) {
            URLS.put(wmsUrlDB.getInterfaceName(), wmsUrlDB.getUrlAddr());
        }
    }

    public static void initProgrammeMap() {
        ProgrammeServiceImpl programmeService = SpringContextHolder.getBean(ProgrammeServiceImpl.class);
        PortDBServiceImpl portDBService = SpringContextHolder.getBean(PortDBServiceImpl.class);
        PROGRAMMES.clear();
        List<PortDB> portDBS = portDBService.list();
        for (PortDB portDB : portDBS) {
            List<ProgrammeDB> list = programmeService.findByPortId(portDB.getPortId());
            PROGRAMMES.put(portDB.getPortCode(), list);
        }
    }

    public static String getUrlByName(String interfaceName) {
        if (interfaceName == null) {
            throw new IllegalArgumentException("接口方法名不能为空");
        }
        String urlAddr = URLS.get(interfaceName);
        if (urlAddr == null) {
            throw new IllegalStateException("找不到接口方法名为: " + interfaceName + "对应的路径");
        }
        return urlAddr;
    }

    public static List<ProgrammeDB> getProgrammeByPortAndType(String portCode, PortModel portModel) {
        List<ProgrammeDB> programmeDBS = PROGRAMMES.get(portCode);
        return programmeDBS.stream().filter(programmeDB -> programmeDB.getProgrammeType().equals(portModel.getVal())).collect(Collectors.toList());
    }

    public static List<ProgrammeDB> getProgrammeByPortAndTypeAndCoord(String portCode, String coord, PortModel portModel) {
        List<ProgrammeDB> programmeDBS = getProgrammeByPortAndType(portCode, portModel);
        return programmeDBS.stream().filter(programmeDB -> programmeDB.getCoords().contains(coord)).collect(Collectors.toList());
    }

    public static Boolean isTimeOut(Rgv rgv) {
//        long batteryTime = SystemInit.wareHouseDB.getBatteryTime() * 24 * 36;
//        batteryTime = batteryTime * 100000L;
//        long longTime = 0;
//        if (rgv.getRgvDB().getBatteryFullTime() != null) {
//            longTime = System.currentTimeMillis() - rgv.getRgvDB().getBatteryFullTime().getTime();
//        }
//        return longTime > batteryTime;
        return false;
    }

    public static void removeLockNode(List<Coord> nodeList) {
        if (CollectionUtils.isNotEmpty(nodeList)) {
            List<Coord> list = Lists.newArrayList();
            for (Coord coord : nodeList) {
                Node node = Node.parseGrid(coord.toString());
                Set<Node> nodeSet = LockNodeManager.needLockNode(node);
                nodeSet.stream().filter(node1 -> {
                    if (LockNodeManager.checkNodesLocked(node1)) {
                        list.add(coord);
                    }
                    return false;
                }).count();
            }
            nodeList.removeAll(list);
        }
    }

    public static void setExpirationTime(Date date) {
        SystemInit.expirationDate = date;
    }

    public static void setExpirationMsg(String msg) {
        SystemInit.expirationMsg = msg;
    }

    /**
     * 单体输送线
     *
     * @param deviceId
     * @return
     */
    public static HandleMonomerConveyorOper plcMonomerConveyorDevice(Integer deviceId) {
        PlcDeviceDB plcDeviceDB = plcDeviceDBService.getPlcDevById(deviceId);
        MonomerConveyorOper mco = (MonomerConveyorOper) Plc.deviceBaseNameMap.get(plcDeviceDB.getDeviceName());
        HandleMonomerConveyorOper hmco = new HandleMonomerConveyorOper();
        hmco.setDeviceId(deviceId);
        hmco.setDeviceName(plcDeviceDB.getDeviceName());
        if (mco == null) {
            hmco.setReadyState("离线");
            return hmco;
        }

        hmco.setReadyState(mco.getPlc().getPlcStatus().getDescription());
        //设备类型
        hmco.setDeviceState(mco.getCurrentDeviceType()==1?"单体输送线":"未知");
        //设备位移量
        hmco.setMovement(Integer.toString(mco.getMovement()));
        //输送线自动速度
        hmco.setConveyorAutoSpeed(Integer.toString(mco.getConveyorAutoSpeed()));
        //输送线自动加速时间
        hmco.setConveyorAutoAcc(Integer.toString(mco.getConveyorAutoAcc()));
        //输送线自动减速时间
        hmco.setConveyorAutoDec(Integer.toString(mco.getConveyorAutoDec()));
        //输送线手动速度
        hmco.setConveyorManualSpeed(Integer.toString(mco.getConveyorManualSpeed()));
        //输送线手动加速时间
        hmco.setConveyorManualAcc(Integer.toString(mco.getConveyorManualAcc()));
        //输送线手动减速时间
        hmco.setConveyorManualDec(Integer.toString(mco.getConveyorManualDec()));
        //单体输送线（含自动门，翻转机构）
        hmco.setTaskAction(Integer.toString(mco.getTaskAction()));
        //故障清除
        hmco.setClearError(mco.isClearError() ? "故障清除" : "无");
        //系统急停
        hmco.setStopState(mco.isStopState() ? "急停" : "未急停");
        //任务号
        hmco.setTaskNo(mco.getTaskNo());
        hmco.setStartNo(mco.getTaskStartLocation());
        hmco.setEndNo(mco.getTaskEndLocation());
        //系统手动模式/自动本地
        String mode="未知";
        if(mco.isControllerMode()){
            mode="自动";
        } else {
            mode="手动";
        }
        hmco.setControllerMode(mode);
        //手动输送线正转
        hmco.setManualForward(mco.isManualForward() ? "运行中" : "未运行");
        //手动输送线反转
        hmco.setManualReverse(mco.isManualReverse() ? "运行中" : "未运行");
        //WCS可控=就绪/未就绪
        hmco.setIsControl(mco.isControl() ? "就绪" : "未就绪");
        //设备正在运行中
        hmco.setDeviceState(mco.isRunning() ? "运行中" : "未运行");
        //故障报警状态
        hmco.setErrorState(mco.isErrorState() ? "故障" : "正常");
        //镜反光电1
        hmco.setSignal1(mco.isInCargoSignalValid() ? "有信号" : "无信号");
        //镜反光电2
        hmco.setSignal2(mco.isOutCargoSignalValid() ? "有信号" : "无信号");
        // 入库信号
        hmco.setAskInCargo(mco.getIfAskInCargo() ? "有信号" : "无信号");
        hmco.setShapeCanRead(mco.isShapeCanRead() ? "可读" : "不可读");
        hmco.setHasForkCar(mco.isForkCarSignal() ? "有叉车" : "无叉车");
        //故障码
        Integer code = mco.getErrorInfo();
        hmco.setErrorInfo((code == null || code.equals(0)) ? "暂无" :
                codeDBService.getCodeDescByType(CodeType.SINGLE_CONVERY.getValue(), code));
        hmco.setLiftCommState(analyzeConveryCommErrorInfo(mco));
        //校准位
        hmco.setCheckNo(Integer.toString(mco.getCheckNo()));
        //当前设备类型
        hmco.setCurrentDeviceType(SinglePlcDeviceType.parseValue(mco.getCurrentDeviceType()).toString());
        hmco.setDeviceDes(mco.getStatus());
        return hmco;
    }

    private static String analyzeConveryCommErrorInfo(MonomerConveyorOper mco) {
        int error1 = mco.getLiftCommError1();
        int error2 = mco.getLiftCommError2() & 0b1111;

        if (error1 == 0 && error2 == 0) {
            return "暂无";
        }

        return analyzeLiftErrorInfo(error2, analyzeLiftErrorInfo(error1, new StringBuffer())).toString();
    }

    private static StringBuffer analyzeLiftErrorInfo(int error, StringBuffer sb) {
        if (error != 0) {
            int index = 0;
            while (error == 0) {
                if ((error & 1) == 1) {
                    if (index == 0) {
                        sb.append("主站PLC与提升机通讯中断");
                    } else {
                        if (StringUtils.isNotEmpty(sb.toString())) {
                            sb.append(";");
                        }

                        if (index % 2 == 0) {
                            sb.append("主站与提升机" + (index / 2) + "层左PLC通讯中断");
                        } else {
                            sb.append("主站与提升机" + (index / 2) + "层右PLC通讯中断");
                        }
                    }
                }

                error >>= 1;
            }
        }

        return sb;
    }

    /**
     * 通过外部设备所关联plcId查找 外部设备
     *
     * @param deviceId
     * @return
     */
    public static HandleAutoTraversingOper plcAutoTraversingDevice(Integer deviceId) {
        PlcDeviceDB plcDeviceDB = plcDeviceDBService.getPlcDevById(deviceId);
        AutoTraversingOper autoTraversingOper = (AutoTraversingOper) Plc.deviceBaseNameMap.get(plcDeviceDB.getDeviceName());
        HandleAutoTraversingOper hato = new HandleAutoTraversingOper();
        hato.setDeviceId(deviceId);
        if (autoTraversingOper == null || org.springframework.util.StringUtils.isEmpty(deviceId)) {
            hato.setReadyState("离线");
            return hato;
        }
        hato.setReadyState(autoTraversingOper.getPlc().getPlcStatus().getDescription());
        //设备类型
        hato.setDeviceType(autoTraversingOper.getCurrentDeviceType()==9?"自动横移机":"未知");
        //设备位移量
        hato.setMovement(Integer.toString(autoTraversingOper.getMovement()));
        //横移自动速度
        hato.setTraverseAutoSpeed(Integer.toString(autoTraversingOper.getTraverseAutoSpeed()));
        //横移自动加速时间
        hato.setTraverseAutoAcc(Integer.toString(autoTraversingOper.getTraverseAutoAcc()));
        //横移自动减速时间
        hato.setTraverseAutoDec(Integer.toString(autoTraversingOper.getTraverseAutoDec()));
        //横移手动速度
        hato.setTraverseManualSpeed(Integer.toString(autoTraversingOper.getTraverseManualSpeed()));
        //横移手动加速时间
        hato.setTraverseManualAcc(Integer.toString(autoTraversingOper.getTraverseManualAcc()));
        //横移手动减速时间
        hato.setTraverseManualDec(Integer.toString(autoTraversingOper.getTraverseManualDec()));
        //输送线自动速度
        hato.setConveyorAutoSpeed(Integer.toString(autoTraversingOper.getConveyorAutoSpeed()));
        //输送线自动加速时间
        hato.setConveyorAutoAcc(Integer.toString(autoTraversingOper.getConveyorAutoAcc()));
        //输送线自动减速时间
        hato.setConveyorAutoDec(Integer.toString(autoTraversingOper.getConveyorAutoDec()));
        //输送线手动速度
        hato.setConveyorManualSpeed(Integer.toString(autoTraversingOper.getConveyorManualSpeed()));
        //输送线手动加速时间
        hato.setConveyorManualAcc(Integer.toString(autoTraversingOper.getConveyorManualAcc()));
        //输送线手动减速时间
        hato.setConveyorManualDec(Integer.toString(autoTraversingOper.getConveyorManualDec()));
        //单体设备运行（含自动门，翻转机构）
        hato.setTaskAction(Integer.toString(autoTraversingOper.getTaskAction()));
        //自动横移机
        hato.setAutoTraversing(Integer.toString(autoTraversingOper.getAutoTraversing()));
        //故障清除
        hato.setClearError(autoTraversingOper.isClearError() ? "故障清除" : "无");
        //外形检测开启
        hato.setIsOpenShape(autoTraversingOper.isOpenShape() ? "开启" : "关闭");
        //扫码故障灯
        hato.setIsOpenBcr(autoTraversingOper.isOpenBcr() ? "打开" : "关闭");
        //超重灯
        hato.setIsOpenOverweight(autoTraversingOper.isOpenOverweight() ? "打开" : "关闭");
        //系统急停
        hato.setStopState(autoTraversingOper.isStopState() ? "急停" : "未急停");
        //系统手动模式/自动本地
        String mode="未知";
        if(autoTraversingOper.isControllerModeManual()){
            mode="手动";
        }
        if(autoTraversingOper.isControllerModeAuto()){
            mode="自动";
        }
        hato.setControllerMode(mode);
        //手动上升
        hato.setManualUp(autoTraversingOper.isManualUp() ? "运行中" : "未运行");
        //手动下降
        hato.setManualDown(autoTraversingOper.isManualDown() ? "运行中" : "未运行");
        //手动输送线正转
        hato.setManualForward(autoTraversingOper.isManualForward() ? "运行中" : "未运行");
        //手动输送线反转
        hato.setManualReverse(autoTraversingOper.isManualReverse() ? "运行中" : "未运行");
        //故障复位
        hato.setClearError1(autoTraversingOper.isClearError1() ? "有" : "无");
        //WCS可控=就绪/未就绪
        hato.setIsControl(autoTraversingOper.isControl() ? "就绪" : "未就绪");
        //设备正在运行中
        hato.setDeviceState(autoTraversingOper.isRunning() ? "运行中" : "未运行");
        //升降正在运行中
        hato.setElevatorState(autoTraversingOper.isElevatorState() ? "运行中" : "未运行");
        //输送线正在运行
        hato.setConveyorState(autoTraversingOper.isConveyorState() ? "运行中" : "未运行");
        //故障报警状态
        hato.setErrorState(autoTraversingOper.isError() ? "故障" : "正常");
        //镜反光电1
        hato.setSignal1(autoTraversingOper.inCargoSignal() ? "到位" : "未到位");
        //镜反光电2
        hato.setSignal2(autoTraversingOper.outCargoSignal() ? "到位" : "未到位");
        //输送线1到位
        hato.setInPlaceSignal1(autoTraversingOper.isInPlaceSignal1() ? "到位" : "未到位");
        //输送线原点到位
        hato.setInPlaceSignal0(autoTraversingOper.isInMidPlace() ? "到位" : "未到位");
        //输送线3到位
        hato.setInPlaceSignal3(autoTraversingOper.isInPlaceSignal3() ? "到位" : "未到位");
        //输送线1方向自动门升到位
        hato.setAutoDoorRise1(autoTraversingOper.isAutoDoorRise1() ? "到位" : "未到位");
        //输送线1方向自动门降到位
        hato.setAutoDoorDrop1(autoTraversingOper.isAutoDoorDrop1() ? "到位" : "未到位");
        //输送线1方向自动门故障
        hato.setAutoDoorError1(autoTraversingOper.isAutoDoorError1() ? "故障" : "正常");
        //输送线3方向自动门升到位
        hato.setAutoDoorRise3(autoTraversingOper.isAutoDoorRise3() ? "到位" : "未到位");
        //输送线3方向自动门降到位
        hato.setAutoDoorDrop3(autoTraversingOper.isAutoDoorDrop3() ?  "到位" : "未到位");
        //输送线3方向自动门故障
        hato.setAutoDoorError3(autoTraversingOper.isAutoDoorError3() ? "故障" : "正常");
        //故障码
        if (autoTraversingOper.errorCode() == null || autoTraversingOper.errorCode() == 0) {
            hato.setErrorInfo("");
        } else {
            hato.setErrorInfo(codeDBService.getCodeDescByType(CodeType.PLC_NEW.getValue(), autoTraversingOper.errorCode()));
        }
        //校准位
        hato.setCheckNo(Integer.toString(autoTraversingOper.getCheckNo()));
        //当前设备类型
        hato.setCurrentDeviceType(SinglePlcDeviceType.parseValue(autoTraversingOper.getDeviceType()).toString());
        hato.setDeviceName(plcDeviceDB.getDeviceName());
        return hato;
    }

    public static LifterEventInterface getLifterEvent(LifterOper lifterOper) {
        if (lifterOper instanceof TwoDirectionRgvLifterOper) {
            return SpringContextHolder.getBean(TwoDirectionRgvLifterEvent.class);
        } else if (lifterOper instanceof ForkLifterOper) {
            return SpringContextHolder.getBean(ForkLifterEvent.class);
        }
        return SpringContextHolder.getBean(OriginalLifterEvent.class);
    }

    /**
     * 牙叉升降机信息
     *
     * @param deviceId
     * @return
     */
    public static HandleToothHoistOper plcToothHoistDevice(Integer deviceId) {
        PlcDeviceDB plcDeviceDB = plcDeviceDBService.getPlcDevById(deviceId);
        ToothHoistOper toothHoistOper = (ToothHoistOper) Plc.deviceBaseNameMap.get(plcDeviceDB.getDeviceName());
        HandleToothHoistOper handleToothHoistOper = new HandleToothHoistOper();
        handleToothHoistOper.setDeviceId(deviceId);
        if (org.springframework.util.StringUtils.isEmpty(deviceId) || toothHoistOper == null) {
            handleToothHoistOper.setReadyState("离线");
            return handleToothHoistOper;
        }
        //任务号
        handleToothHoistOper.setTaskNo(toothHoistOper.getTaskNo());
        handleToothHoistOper.setStartNo(toothHoistOper.getTaskStartLocation());
        handleToothHoistOper.setEndNo(toothHoistOper.getTaskEndLocation());
        handleToothHoistOper.setReadyState(toothHoistOper.getPlc().getPlcStatus().getDescription());
        //设备类型
        handleToothHoistOper.setDeviceType(toothHoistOper.getCurrentDeviceType() == 7 ? "牙叉升降机" : "未知");
        //设备位移量
        handleToothHoistOper.setMovement(Integer.toString(toothHoistOper.getMovement()));
        //升降自动速度
        handleToothHoistOper.setLiftAutoSpeed(Integer.toString(toothHoistOper.getLiftAutoSpeed()));
        //升降自动加速时间
        handleToothHoistOper.setLiftAutoAcc(Integer.toString(toothHoistOper.getLiftAutoAcc()));
        //升降自动减速时间
        handleToothHoistOper.setLiftAutoDec(Integer.toString(toothHoistOper.getLiftAutoDec()));
        //升降手动速度
        handleToothHoistOper.setLiftManualSpeed(Integer.toString(toothHoistOper.getLiftManualSpeed()));
        //升降手动加速时间
        handleToothHoistOper.setLiftManualAcc(Integer.toString(toothHoistOper.getLiftManualAcc()));
        //升降手动减速时间
        handleToothHoistOper.setLiftManualDec(Integer.toString(toothHoistOper.getLiftManualDec()));
        //输送线自动速度
        handleToothHoistOper.setConveyorAutoSpeed(Integer.toString(toothHoistOper.getConveyorAutoSpeed()));
        //输送线自动加速时间
        handleToothHoistOper.setConveyorAutoAcc(Integer.toString(toothHoistOper.getConveyorAutoAcc()));
        //输送线自动减速时间
        handleToothHoistOper.setConveyorAutoDec(Integer.toString(toothHoistOper.getConveyorAutoDec()));
        //输送线手动速度
        handleToothHoistOper.setConveyorManualSpeed(Integer.toString(toothHoistOper.getConveyorManualSpeed()));
        //输送线手动加速时间
        handleToothHoistOper.setConveyorManualAcc(Integer.toString(toothHoistOper.getConveyorManualAcc()));
        //输送线手动减速时间
        handleToothHoistOper.setConveyorManualDec(Integer.toString(toothHoistOper.getConveyorManualDec()));
        //牙叉升降机运行
        handleToothHoistOper.setTaskAction(Integer.toString(toothHoistOper.getTaskAction()));
        //故障清除
        handleToothHoistOper.setClearError(toothHoistOper.isClearError() ? "故障清除" : "无");
        //外形检测开启
        handleToothHoistOper.setIsOpenShape(toothHoistOper.isOpenShape() ? "开启" : "关闭");
        //扫码故障灯
        handleToothHoistOper.setIsOpenBcr(toothHoistOper.isOpenBcr() ? "打开" : "关闭");
        //超重灯
        handleToothHoistOper.setIsOpenOverweight(toothHoistOper.isOpenOverweight() ? "打开" : "关闭");
        //系统急停
        handleToothHoistOper.setStopState(toothHoistOper.isStopState() ? "急停" : "未急停");
        //系统手动模式/自动本地
        String mode = "未知";
        if (toothHoistOper.isControllerModeManual()) {
            mode = "手动";
        } else {
            mode = "自动";
        }
        if (toothHoistOper.isControllerModeLocal()) {
            mode = "本地";
        } else {
            mode += "远程";
        }
        handleToothHoistOper.setControllerMode(mode);
        //手动上升
        handleToothHoistOper.setManualUp(toothHoistOper.isManualUp() ? "运行中" : "未运行");
        //手动下降
        handleToothHoistOper.setManualDown(toothHoistOper.isManualDown() ? "运行中" : "未运行");
        //手动输送线正转
        handleToothHoistOper.setManualForward(toothHoistOper.isManualForward() ? "运行中" : "未运行");
        //手动输送线反转
        handleToothHoistOper.setManualReverse(toothHoistOper.isManualReverse() ? "运行中" : "未运行");
        //故障复位
        handleToothHoistOper.setClearError1(toothHoistOper.isClearError1() ? "有" : "无");
        //WCS可控
        handleToothHoistOper.setIsControl(toothHoistOper.isControl() ? "就绪" : "未就绪");
        //设备正在运行中
        handleToothHoistOper.setDeviceState(toothHoistOper.isDeviceState() ? "运行中" : "未运行");
        //升降正在运行中
        handleToothHoistOper.setElevatorState(toothHoistOper.isElevatorState() ? "运行中" : "未运行");
        //输送线正在运行
        handleToothHoistOper.setConveyorState(toothHoistOper.isConveyorState() ? "运行中" : "未运行");
        //故障报警状态
        handleToothHoistOper.setErrorState(toothHoistOper.isErrorState() ? "报警" : "不报警");
        //入库请求
        handleToothHoistOper.setRequestIn(toothHoistOper.isRequestIn() ? "请求" : "无");
        //上升到位
        handleToothHoistOper.setRiseInPlace(toothHoistOper.isRiseInPlace() ? "到位" : "未到位");
        //下降到位
        handleToothHoistOper.setDropInPlace(toothHoistOper.isDropInPlace() ? "到位" : "未到位");
        //输送线1到位
        handleToothHoistOper.setInPlaceSignal1(toothHoistOper.isInPlaceSignal1() ? "到位" : "未到位");
        //输送线2到位
        handleToothHoistOper.setInPlaceSignal2(toothHoistOper.isInPlaceSignal2() ? "到位" : "未到位");

        //故障码
        Integer code = toothHoistOper.getErrorInfo();
        handleToothHoistOper.setErrorInfo((code == null || code.equals(0)) ? "暂无" :
                codeDBService.getCodeDescByType(CodeType.SINGLE_CONVERY.getValue(), code));

        //校准位
        handleToothHoistOper.setCheckNo(Integer.toString(toothHoistOper.getCheckNo()));
        handleToothHoistOper.setDeviceDes(toothHoistOper.getStatus());
        //当前设备类型
        handleToothHoistOper.setCurrentDeviceType(
                SinglePlcDeviceType.parseValue(toothHoistOper.getCurrentDeviceType()).toString());
        handleToothHoistOper.setDeviceName(plcDeviceDB.getDeviceName());

        return handleToothHoistOper;
    }

    public static HandleLifterBase lifterBaseDevice(Integer deviceId) {
        PlcDeviceDB plcDeviceDB = plcDeviceDBService.getPlcDevById(deviceId);
        LifterBaseOper lifterBaseOper = (LifterBaseOper) Plc.deviceBaseNameMap.get(plcDeviceDB.getDeviceName());
        HandleLifterBase handleLifterBase = new HandleLifterBase();
        handleLifterBase.setDeviceName(plcDeviceDB.getDeviceName());
        if (lifterBaseOper == null) {
            handleLifterBase.setReadyState("离线");
            return handleLifterBase;
        }
        handleLifterBase.setReadyState(lifterBaseOper.getPlc().getPlcStatus().getDescription());
        handleLifterBase.setServoNo(lifterBaseOper.getServoNo());
        handleLifterBase.setErrorInfo(codeDBService.getCodeDescByType(CodeType.PLC_NEW.getValue(),
                lifterBaseOper.getErrorCode()));
        return handleLifterBase;
    }

    /**
     * 单体拆叠盘机
     *
     * @param deviceId
     * @return
     */
    public static HandleFoldingMachineOper plcFoldingDevice(Integer deviceId) {
        PlcDeviceDB plcDeviceDB = plcDeviceDBService.getPlcDevById(deviceId);
        FoldingOper foldingOper = (FoldingOper) Plc.deviceBaseNameMap.get(plcDeviceDB.getDeviceName());
        HandleFoldingMachineOper handleFoldingMachineOper=new HandleFoldingMachineOper();
        handleFoldingMachineOper.setDeviceId(deviceId);
        handleFoldingMachineOper.setDeviceName(plcDeviceDB.getDeviceName());
        if (foldingOper == null || foldingOper.getPlc().getPlcStatus() == Network.OFF_LINE) {
            handleFoldingMachineOper.setReadyState("离线");
            return handleFoldingMachineOper;
        }
        handleFoldingMachineOper.setCheckNo(foldingOper.getCheckNo());
        handleFoldingMachineOper.setReadyState("在线");
        handleFoldingMachineOper.setControllerMode(foldingOper.getManualMode()?"自动":"手动");
        handleFoldingMachineOper.setIsControl(foldingOper.canControl()?"可控":"不可控");
        handleFoldingMachineOper.setCurrentDeviceType(foldingOper.getDeviceType()==11?"单体拆叠盘机":foldingOper.getDeviceType()+"");
        handleFoldingMachineOper.setPalletNum(foldingOper.getPalletNum());

        //故障码
        Integer code = foldingOper.errorCode();
        handleFoldingMachineOper.setErrorInfo((code == null || code.equals(0)) ? "暂无" :
                codeDBService.getCodeDescByType(CodeType.SINGLE_CONVERY.getValue(), code));

        handleFoldingMachineOper.setUpperInPlace(foldingOper.isUpperInPlace()?"到位":"未到位");
        handleFoldingMachineOper.setDownInPlace(foldingOper.isDownInPlace()?"到位":"未到位");
        handleFoldingMachineOper.setMiddleInPlace(foldingOper.gisMiddleInPlace()?"到位":"未到位");
        handleFoldingMachineOper.setPalletHeight(foldingOper.isPalletHeight()?"超高":"合格");
        handleFoldingMachineOper.setReachInPlace(foldingOper.isReachInPlace()?"到位":"未到位");
        handleFoldingMachineOper.setShrinkInPlace(foldingOper.isShrinkInPlace()?"到位":"未到位");
        handleFoldingMachineOper.setPallet1(foldingOper.isPallet1()?"到位":"未到位");
        handleFoldingMachineOper.setPallet2(foldingOper.isPallet2()?"到位":"未到位");
        handleFoldingMachineOper.setProximitySignal(foldingOper.isProximity()?"到位":"未到位");
        handleFoldingMachineOper.setTaskAction(foldingOper.isRunning()?"运行中":"未运行");
        handleFoldingMachineOper.setStopState(foldingOper.isStopSingal()?"急停":"未急停");
        handleFoldingMachineOper.setTaskNo(foldingOper.getTaskNo());
        handleFoldingMachineOper.setStartNo(foldingOper.getTaskStartLocation());
        handleFoldingMachineOper.setEndNo(foldingOper.getTaskEndLocation());
        handleFoldingMachineOper.setTaskNoComplete(foldingOper.getTaskEndTaskNo());
        handleFoldingMachineOper.setStartNoComplete(foldingOper.getTaskEndStartNo());
        handleFoldingMachineOper.setEndNoComplete(foldingOper.getTaskEndTaskNo());
        handleFoldingMachineOper.setErrorState(foldingOper.isError() ? "故障" : "正常");
        return handleFoldingMachineOper;
    }
}
